﻿#region

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using AutoMapper;
using DomainModel.Domain.Model;
using DomainModel.Domain.Model.MessageAssemblyModel;
using DomainModel.Domain.Model.MessageClipModel;
using DomainModel.Domain.Model.MessageTypeModel;
using DomainModel.Domain.Model.ServiceModel;
using DomainModel.Domain.Model.SubscriptionModel;
using EsbMonitor.Ninject;
using MessageTypeDescriber.Utils;
using NsbMonitorClientService.DataContract;
using NsbMonitorClientService.QueueManager;

#endregion

namespace NsbMonitorClientService
{
    public class NsbMonitorClientServiceImpl : INsbMonitorClientService
    {
        public byte[] GetMessageAssemblyFile(int messageAssemblyId)
        {
            var messageAssembliesRepository = KernelContainer.Get<IMessageAssembliesRepository>();

            var messageAssembly = messageAssembliesRepository.GetById(new MessageAssemblyId(messageAssemblyId));

            String localName = messageAssembly.LocalName;

            byte[] rawData = File.ReadAllBytes(localName);

            return rawData;
        }

        public List<MessageInQueueInfo> GetMessagesInQueue(string queueFullPath)
        {
            var queueReader = KernelContainer.Get<IQueueReader>();

            var messagesFromQueue = queueReader.ReadMessagesFromQueue(queueFullPath);

            List<MessageInQueueInfo> messageInQueueShortInfos = new List<MessageInQueueInfo>();

            foreach (var message in messagesFromQueue)
            {
                String senderId = Encoding.ASCII.GetString(message.SenderId);
                long length = message.BodyStream.Length;

                string content;

                if (length < 2048)
                {
                    using (StreamReader reader = new StreamReader(message.BodyStream))
                    {
                        content = reader.ReadToEnd();
                    }
                }

                else
                {
                    content = " MESSAGE CONTENT IS TOO LONG ";
                }


                messageInQueueShortInfos.Add(new MessageInQueueInfo
                                                 {
                                                     Id = message.Id,
                                                     Label = message.Label,
                                                     SentTime = message.SentTime,
                                                     Size = length,
                                                     Content = content
                                                     //Sender = message.
                                                 }
                    );
            }

            return messageInQueueShortInfos;
        }

        public MessageAssemblyDetails GetMessageAssemblyDetails(int messageAssemblyId)
        {
            var messageAssembliesRepository = KernelContainer.Get<IMessageAssembliesRepository>();

            var messageAssembly = messageAssembliesRepository.GetById(new MessageAssemblyId(messageAssemblyId));
            var servicesRepo = KernelContainer.Get<IServicesRepository>();

            MessageAssemblyDetails messageAssemblyDetails = Mapper.Map<MessageAssembly, MessageAssemblyDetails>(messageAssembly);

            IList<Service> usedBy = servicesRepo.Get(messageAssembly);

            messageAssemblyDetails.UsedBy = Mapper.Map<IList<Service>, List<ServiceNameId>>(usedBy);

            return messageAssemblyDetails;
        }

        public List<MessageTypeShortInfo> GetMessageTypesFromAssembly(int messageAssemblyId)
        {
            var messageAssembliesRepository = KernelContainer.Get<IMessageAssembliesRepository>();

            var messageAssembly = messageAssembliesRepository.GetById(new MessageAssemblyId(messageAssemblyId));

            return Mapper.Map<IList<MessageType>, List<MessageTypeShortInfo>>(messageAssembly.MessageTypesList);
        }

        public List<MessageAssemblyShortInfo> GetAllMessageAssembliesShortInfo()
        {
            var messageAssembliesRepository = KernelContainer.Get<IMessageAssembliesRepository>();

            var allMessageAssemblies = messageAssembliesRepository.GetAll();

            return Mapper.Map<IList<MessageAssembly>, List<MessageAssemblyShortInfo>>(allMessageAssemblies);
        }

        public List<ServiceShortInfo> GetAllServicesShortInfo()
        {
            var servicesRepo = KernelContainer.Get<IServicesRepository>();

            var allServices = servicesRepo.GetAll();

            return Mapper.Map<IList<Service>, List<ServiceShortInfo>>(allServices);
        }

        public List<QueueShortInfo> GetAllQueues()
        {
            var servicesRepo = KernelContainer.Get<IServicesRepository>();
            var exploreMsMq = KernelContainer.Get<IExploreMsMq>();

            HashSet<QueueInfo> allQueues = new HashSet<QueueInfo>();

            IEnumerable<Service> allServices = servicesRepo.GetAll();

            allServices.ToList().ForEach(s =>
                                             {
                                                 allQueues.Add(s.InputQueue);
                                                 allQueues.Add(s.ErrorQueue);
                                                 allQueues.Add(s.AuditQueue);
                                             });

            if (allQueues.Contains(null))
            {
                allQueues.Remove(null);
            }

            foreach (var queueInfo in allQueues)
            {
                try
                {
                    QueueStatus queueStatus = exploreMsMq.QueueStatus(queueInfo.Address);
                    queueInfo.MessagesCount = queueStatus.MessagesCount;
                    queueInfo.OldestMessageTime = queueStatus.OldestMessageTime;
                } catch (Exception ex)
                {
                }
            }

            return Mapper.Map<IEnumerable<QueueInfo>, List<QueueShortInfo>>(allQueues);
        }

        public MessageTypeDetails GetMessageTypeDetails(int typeId)
        {
            var messageTypesRepo = KernelContainer.Get<IMessageTypesRepository>();
            MessageType messageType = messageTypesRepo.GetById(new MessageTypeId(typeId));


            List<MessageTypeMember> members = new List<MessageTypeMember>();

            foreach (var member in messageType.TypeDescription.TypeFullDescription.Elements)
            {
                MessageTypeMember messageTypeMember = new MessageTypeMember();
                messageTypeMember.Signature = member.Signature;
                messageTypeMember.MemberType = member.MemberType;
                messageTypeMember.Description = member.Description;
                members.Add(messageTypeMember);
            }

            MessageTypeDetails messageTypeDetails = new MessageTypeDetails();
            messageTypeDetails.FullName = messageType.Name;
            messageTypeDetails.Name = NameUtils.Short(messageType.Name);
            messageTypeDetails.Members = members;

            return messageTypeDetails;
        }

        public ServiceDetails GetServiceDetails(int serviceId)
        {
            var servicesRepo = KernelContainer.Get<IServicesRepository>();
            var subscriptionsRepo = KernelContainer.Get<ISubscriptionsRepository>();

            var service = servicesRepo.GetById(new ServiceId(serviceId));

            IList<MessageType> messageTypesExposedByPublisher = subscriptionsRepo.GetMessageTypesExposedByPublisher(service);
            IList<Subscription> subscribedTo = subscriptionsRepo.GetBySubscriber(service);
            IList<Subscription> subscribedBy = subscriptionsRepo.GetByPublisher(service);

            IList<MessageTypeNameId> messageTypesNameIdExposedByPublisher = Mapper.Map<IList<MessageType>, IList<MessageTypeNameId>>(messageTypesExposedByPublisher);
            IList<MessageAssemblyNameId> messageAssembliesNameIdUsedByService = Mapper.Map<IEnumerable<MessageAssembly>, IList<MessageAssemblyNameId>>(service.MessageAssembliesSet);
            IList<SubscribedToShortInfo> subscribedToShortInfo = Mapper.Map<IEnumerable<Subscription>, IList<SubscribedToShortInfo>>(subscribedTo);
            IList<SubscribedByShortInfo> subscribedByShortInfo = Mapper.Map<IEnumerable<Subscription>, IList<SubscribedByShortInfo>>(subscribedBy);

            ServiceDetails serviceDetails = Mapper.Map<Service, ServiceDetails>(service);
                                                 
            serviceDetails.Publishes = messageTypesNameIdExposedByPublisher;
            serviceDetails.UsesMessageAssemblies = messageAssembliesNameIdUsedByService;
            serviceDetails.SubscribedTo = subscribedToShortInfo;
            serviceDetails.SubscribedBy = subscribedByShortInfo;

            List<String> actsAs = new List<string>();

            if (service.IsPublisher())
            {
                actsAs.Add("Publisher");
            }
            if (service.IsSubscriber())
            {
                actsAs.Add("Subscriber");
            }
            if (service.IsHandler())
            {
                actsAs.Add("Handler");
            }

            serviceDetails.ActsAs = actsAs;

            return serviceDetails;
        }

        public IList<MessageClipInfo> GetAllMessageClips()
        {
            var messageClipsRepository = KernelContainer.Get<IMessageClipsRepository>();

            IList<MessageClip> messageClips = messageClipsRepository.GetAll();

            return Mapper.Map<IList<MessageClip>, IList<MessageClipInfo>>(messageClips);
        }

        public void SaveMessageClip(MessageClipInfo messageClipInfo)
        {
            var messageClipsRepository = KernelContainer.Get<IMessageClipsRepository>();

            MessageClip messageClip = new MessageClip(messageClipsRepository.NextMessageClipId());

            messageClip.Content = messageClipInfo.Content;
            messageClip.Name = messageClipInfo.Name;
            messageClip.Label = messageClip.Label;


            messageClipsRepository.Store(messageClip);
        }

        public void DiscardMessageClip(int messageClipId)
        {
            var messageClipsRepository = KernelContainer.Get<IMessageClipsRepository>();

            var messageClip = messageClipsRepository.GetById(new MessageClipId(messageClipId));

            if (messageClip != null)
            {
                messageClipsRepository.Delete(messageClip);
            }
        }

        public string SendMessageToQueue(MessageToSendToQueue messageToSendToQueue)
        {
            var queueSender = KernelContainer.Get<IQueueSender>();

            string fullQueuePath = messageToSendToQueue.Destination;

            string content = messageToSendToQueue.Content;

            string label = messageToSendToQueue.Label;
            string id = queueSender.SendMessageToQueue(fullQueuePath, content, label);

            return id;
        }

        public void PurgeQueue(string queueFullPath)
        {
            var queuePurger = KernelContainer.Get<IQueuePurger>();

            queuePurger.PurgeQueue(queueFullPath);
        }

        public void RemoveMessageFromQueue(string queueFullPath, string messageId)
        {
            var queueReader = KernelContainer.Get<IQueueReader>();

            queueReader.ReadMessageById(queueFullPath, messageId);
        }

        public void MoveMessageFromQueueToQueue(string sourceQueueFullPath, string messageId, string destinationQueueFullPath)
        {
            throw new NotImplementedException();
        }

        public void CopyMessageFromQueueToQueue(string sourceQueueFullPath, string messageId, string destinationQueueFullPath)
        {
            throw new NotImplementedException();
        }
    }
}